package edu.zju.gis.dldsj.type;

import java.io.Serializable;
import java.util.Iterator;
import java.util.List;

public class Dataset<T> implements Iterable<T>, Serializable {
    private StructType structType;
    private List<T> items;
    private QueryBuilder queryBuilder;

    public Dataset(List<T> items) {
        this(null, items);
    }

    public Dataset(StructType structType, List<T> items) {
        this.structType = structType;
        this.items = items;
    }

    public StructType getStructType() {
        return structType;
    }

    public void setStructType(StructType structType) {
        this.structType = structType;
    }

    public int getCount() {
        return items.size();
    }

    public boolean sqlable() {
        return structType != null && structType.getFieldCount() > 0;
    }

    public List<String> getColumns() {
        return structType.fieldNames();
    }

    public Column col(String name) {
        return new Column(structType.nameToField().get(name));
    }

    public void printSchema() {
        System.out.println("root");
        structType.getFields().forEach(field -> System.out.printf("  |-- %s: %s (nullable = %s)\n", field.getName()
                , field.getDataType().name(), field.isNullable()));
        System.out.println();
    }

    public void show() {
        System.out.println(String.join("|", structType.fieldNames()));
        for (T item : items) {
            System.out.println(item);
        }
    }

    @Override
    public Iterator<T> iterator() {
        return items.iterator();
    }

    /************ 以下查询过程通过reader动态地进行，基于JDBC、HBase、ES等的操作转移到原生接口的封装上 ***********/
//    public Dataset<Row> execute() throws SQLException {
//        if (!sqlable()) {
//            throw new UnsupportedOperationException();
//        }
//        if (reader instanceof JdbcReader) {
//            JdbcReader jdbcReader = (JdbcReader) reader;
//            String sql = String.format("select %s from %s", queryBuilder.select, jdbcReader.getTable());
//            String where = "";
//            if (!queryBuilder.filter.isEmpty()) {
//                where = String.join(" and ", queryBuilder.filter);
//            }
//            if (!queryBuilder.where.isEmpty()) {
//                where += (where.isEmpty() ? "" : " and ") + queryBuilder.where;
//            }
//            if (!where.isEmpty())
//                sql += " where " + where;
//            if (!queryBuilder.groupBy.isEmpty()) {
//                sql += " group by " + queryBuilder.groupBy;
//            }
//            if (!queryBuilder.orderBy.isEmpty()) {
//                sql += " order by " + queryBuilder.orderBy;
//            }
//            sql += String.format(" limit %d, %d", queryBuilder.offset, queryBuilder.size);
//            return jdbcReader.queryDataset(sql);
//        } else if (reader instanceof DSVHelper) {
//            StructFileQuerier qier = new StructFileQuerier((Dataset<Row>) this, queryBuilder.select,
//                    queryBuilder.where, queryBuilder.filter, queryBuilder.orderBy, queryBuilder.groupBy, queryBuilder.offset, queryBuilder.size);
//            return qier.execute();
//        } else {
//            throw new UnsupportedOperationException();
//        }
//    }
    public Dataset<T> select(String... cols) {
        queryBuilder.select(String.join(",", cols));
        return this;
    }

    public Dataset<T> filter(String filter) {
        queryBuilder.filter(filter);
        return this;
    }

    public Dataset<T> where(String where) {
        queryBuilder.where(where);
        return this;
    }

    public Dataset<T> groupBy(String... cols) {
        queryBuilder.groupBy(String.join(",", cols));
        return this;
    }

    public Dataset<T> orderBy(String... cols) {
        queryBuilder.orderBy(String.join(",", cols));
        return this;
    }

    public Dataset<T> limit(long offset, long size) {
        queryBuilder.limit(offset, size);
        return this;
    }

}
